package me.zxc.crawler.bangumi;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import me.zxc.utils.ExportUtil;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.File;
import java.net.SocketTimeoutException;
import java.util.Scanner;

/**
 * 根据bangumi番剧id编号获取角色声优对照，制作公司等基础信息
 */
@Slf4j
public class CharacterParser {
    /**
     * 番名id（地址栏或光标悬停时在url中可以看到）
     */
    private static String BANGUMI_ID;

    /**
     * 角色名翻译（可选）
     * 防止全是片假名看着闹心。现实世界里应该没人名字是一串片假名，所以声优名就不加可选项了。
     */
    private static boolean TRANSLATE_CHARACTER_NAME = false;

    /**
     * 打印到控制台（false则保存为txt）
     */
    private static final boolean PRINT = false;

    /**
     * 角色页url
     */
    private static final String CHARACTER_PAGE = "https://bangumi.tv/subject/${bid}/characters";

    /**
     * 番剧详情页
     */
    private static Document bangumiPage;

    private static final Scanner scanner = new Scanner(System.in);

    public static void main(String[] args) {
        while (true) {
            inputParams();
            log.info("处理中，请稍后……");
            long start = System.currentTimeMillis();
            try {
                // 连接
                bangumiPage = Jsoup.connect(CHARACTER_PAGE.split("\\$\\{bid}")[0] + BANGUMI_ID).get();
                Document characterPage = Jsoup.connect(CHARACTER_PAGE.replace("${bid}", BANGUMI_ID)).get();

                // 获取番名
                String bName = bangumiPage.body().getElementsByClass("nameSingle").get(0)
                        .getElementsByTag("a").get(0)
                        .html();
                String bNameCh = getInfoBoxValue("中文名");
                String fullName = bName;
                if (StrUtil.isNotBlank(bNameCh)) {
                    fullName += "（" + bNameCh + "）";
                }
                StringBuilder result = new StringBuilder(fullName);
                // 获取动画制作公司
                String title = "动画制作";
                String value = getInfoBoxValue(title);
                result.append("\n\n");
                result.append(title).append("：").append(value).append("\n");
                // 获取角色声优表
                result.append("角色声优").append("\n");
                Elements ccList = characterPage.body().getElementsByClass("columns clearit");
                if (CollectionUtil.isNotEmpty(ccList)) {
                    // columns clearit 唯一
                    Element ccEle = ccList.get(0);
                    Element columnInSubjectA = ccEle.getElementById("columnInSubjectA");
                    assert columnInSubjectA != null;
                    Elements roleList = columnInSubjectA.getElementsByClass("light_odd");
                    if (CollectionUtil.isNotEmpty(roleList)) {
                        for (Element role : roleList) {
                            // 角色名
                            String roleName = role.getElementsByTag("h2").get(0)
                                    .getElementsByTag("a").get(0)
                                    .html();
                            // 声优名
                            Elements actorBadge = role.getElementsByClass("actorBadge clearit");
                            String cvName;
                            if (actorBadge.isEmpty()) {
                                cvName = "暂无数据";
                            } else {
                                cvName = actorBadge.get(0)
                                        .getElementsByTag("p").get(0)
                                        .getElementsByTag("a").get(0)
                                        .html();
                            }
                            result.append(roleName);
                            // 角色名添加翻译
                            if (TRANSLATE_CHARACTER_NAME) {
                                // 有的人物没有翻译备注标签
                                Elements tips = role.getElementsByTag("h2").get(0)
                                        .getElementsByClass("tip");
                                if (!tips.isEmpty()) {
                                    String tip = tips.get(0).html().substring(2);
                                    result.append("／").append(tip);
                                }
                            }
                            result.append("：").append(cvName).append("\n");
                        }
                    }
                }
                // 打印或保存结果
                if (PRINT) {
                    System.out.println(result);
                } else {
                    String savePath = new File("saved").getCanonicalPath();
                    ExportUtil.createPlaintext(result.toString(), savePath, bName);
                }
            } catch (SocketTimeoutException timeoutException) {
                log.error("连接超时，请重试！");
            } catch (Exception e) {
                e.printStackTrace();
            }
            long end = System.currentTimeMillis();
            log.info("处理总耗时 " + (end - start) + " ms");
            System.out.print("是否继续查询下一个(y/n) > ");
            String flag = scanner.next();
            if ("n".equalsIgnoreCase(flag) || "no".equalsIgnoreCase(flag)) {
                System.out.println("Bye");
                break;
            }
        }
    }

    /**
     * 终端界面下用户输入参数
     */
    private static void inputParams() {
        System.out.print("请输入番剧id > ");
        BANGUMI_ID = scanner.next();
        System.out.print("是否翻译角色名(y/n) > ");
        String flag = scanner.next();
        if ("y".equalsIgnoreCase(flag) || "yes".equalsIgnoreCase(flag)) {
            TRANSLATE_CHARACTER_NAME = true;
        }
    }

    /**
     * 通过键获取infoBox信息
     *
     * @param infoKey 番剧信息的key
     * @return 番剧信息
     */
    private static String getInfoBoxValue(String infoKey) {
        String value = null;
        Element infoboxEle = bangumiPage.getElementById("infobox");
        assert infoboxEle != null;
        Elements liList = infoboxEle.getElementsByTag("li");
        if (CollectionUtil.isNotEmpty(liList)) {
            for (Element liTag : liList) {
                String key = liTag.getElementsByTag("span").get(0).html();
                if (StrUtil.isNotBlank(key) && key.contains(infoKey)) {
                    // 如果是a标签，取a标签里面的值 否则去li标签里面的文本后半段
                    if (liTag.getElementsByTag("a").hasText()) {
                        value = liTag.getElementsByTag("a").get(0).html();
                    } else {
                        value = liTag.text().split(": ")[1];
                    }
                    // 找到即退出 减少循环次数
                    break;
                }
            }
        }
        return value;
    }
}
